/*
 * MIT License
 *
 * Copyright (c) 2021-2099 Oscura (xingshuang) <xingshuang_cool@163.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.github.xingshuangs.iot.protocol.mp4.model;

import com.github.xingshuangs.iot.protocol.mp4.enums.EMp4Type;
import com.github.xingshuangs.iot.utils.HexUtil;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.junit.Assert.assertArrayEquals;


public class Mp4MoovBoxTest {

    private List<Mp4SampleData> samples;

    private Mp4TrackInfo trackInfo;

    @Before
    public void init() {
        this.samples = new ArrayList<>();
        Mp4SampleData data = new Mp4SampleData();
        data.setData(new byte[5459]);
        data.setDuration(3600);
        data.setCts(0);
        Mp4SampleFlag flag = new Mp4SampleFlag();
        flag.setDependedOn(2);
        data.setFlags(flag);
        this.samples.add(data);

        data = new Mp4SampleData();
        data.setData(new byte[4994]);
        data.setDuration(3600);
        data.setCts(0);
        flag = new Mp4SampleFlag();
        flag.setDependedOn(1);
        flag.setIsNonSync(1);
        data.setFlags(flag);
        this.samples.add(data);

        this.trackInfo = new Mp4TrackInfo();
        this.trackInfo.setId(1);
        this.trackInfo.setType("video");
        this.trackInfo.setTimescale(90000);
        this.trackInfo.setDuration(90000);
        this.trackInfo.setWidth(1920);
        this.trackInfo.setHeight(1080);
        this.trackInfo.setSps(new byte[]{0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80});
        this.trackInfo.setPps(new byte[]{0x68, (byte) 0xEE, 0x3C, (byte) 0xB0});
        this.trackInfo.setSampleData(this.samples);
    }

    @Test
    public void mp4Type() {
        System.out.println(HexUtil.toHexString(EMp4Type.TFHD.getByteArray()));
    }

    @Test
    public void mp4MoovBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x02, (byte) 0x83,
                0x6D, 0x6F, 0x6F, 0x76,

                0x00, 0x00, 0x00, 0x6C, 0x6D, 0x76, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x5F, (byte) 0x90, 0x00, 0x01, 0x5F, (byte) 0x90, 0x00, 0x01, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,

                0x00, 0x00, 0x01, (byte) 0xE7, 0x74, 0x72, 0x61, 0x6B,
                0x00, 0x00, 0x00, 0x5C, 0x74, 0x6B, 0x68, 0x64, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5F, (byte) 0x90,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x40, 0x00, 0x00, 0x00, 0x07, (byte) 0x80, 0x00, 0x00, 0x04, 0x38, 0x00, 0x00,
                0x00, 0x00, 0x01, (byte) 0x83, 0x6D, 0x64, 0x69, 0x61,
                0x00, 0x00, 0x00, 0x20, 0x6D, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
                0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x5F, (byte) 0x90, 0x00, 0x01, 0x5F, (byte) 0x90, 0x55, (byte) 0xC4, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x2D, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x76, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x56, 0x69, 0x64, 0x65, 0x6F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00,
                0x00, 0x00, 0x01, 0x2E, 0x6D, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x14, 0x76, 0x6D, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
                0x64, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x1C, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x75, 0x72, 0x6C, 0x20, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, (byte) 0xEE, 0x73, 0x74, 0x62, 0x6C, 0x00, 0x00, 0x00, (byte) 0xA2, 0x73, 0x74, (byte) 0x73, 0x64,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, (byte) 0x92, 0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, 0x6C, 0x70, 0x72, 0x6F, 0x2E, 0x72, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11, 0x00, 0x00, 0x00, 0x28, 0x61, 0x76, 0x63, 0x43, 0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04, 0x68, (byte) 0xEE, 0x3C, (byte) 0xB0, 0x00, 0x00, 0x00, 0x14, 0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80, 0x00, 0x2D, (byte) 0xC6, (byte) 0xC0, 0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x14, 0x73, 0x74, 0x73, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x63, 0x6F, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,

                0x00, 0x00, 0x00, 0x28, 0x6D, 0x76, 0x65, 0x78, 0x00, 0x00, 0x00, 0x20, 0x74, 0x72, 0x65, 0x78,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
        };
        Mp4MoovBox box = new Mp4MoovBox(Collections.singletonList(this.trackInfo));
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4MvhdBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x6C,
                0x6D, 0x76, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x02,
                0x00, 0x01, 0x5F, (byte) 0x90,
                0x00, 0x01, 0x5F, (byte) 0x90,
                0x00, 0x01, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x40, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
        };
        Mp4MvhdBox box = new Mp4MvhdBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4TrakBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x01, (byte) 0xE7,
                0x74, 0x72, 0x61, 0x6B,

                0x00, 0x00, 0x00, 0x5C, 0x74, 0x6B, 0x68, 0x64, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5F, (byte) 0x90,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x40, 0x00, 0x00, 0x00, 0x07, (byte) 0x80, 0x00, 0x00, 0x04, 0x38, 0x00, 0x00,

                0x00, 0x00, 0x01, (byte) 0x83, 0x6D, 0x64, 0x69, 0x61,
                0x00, 0x00, 0x00, 0x20, 0x6D, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
                0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x5F, (byte) 0x90, 0x00, 0x01, 0x5F, (byte) 0x90, 0x55, (byte) 0xC4, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x2D, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x76, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x56, 0x69, 0x64, 0x65, 0x6F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00,
                0x00, 0x00, 0x01, 0x2E, 0x6D, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x14, 0x76, 0x6D, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
                0x64, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x1C, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x75, 0x72, 0x6C, 0x20, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, (byte) 0xEE, 0x73, 0x74, 0x62, 0x6C, 0x00, 0x00, 0x00, (byte) 0xA2, 0x73, 0x74, (byte) 0x73, 0x64,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, (byte) 0x92, 0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, 0x6C, 0x70, 0x72, 0x6F, 0x2E, 0x72, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11, 0x00, 0x00, 0x00, 0x28, 0x61, 0x76, 0x63, 0x43, 0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04, 0x68, (byte) 0xEE, 0x3C, (byte) 0xB0, 0x00, 0x00, 0x00, 0x14, 0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80, 0x00, 0x2D, (byte) 0xC6, (byte) 0xC0, 0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x14, 0x73, 0x74, 0x73, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x63, 0x6F, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4TrakBox box = new Mp4TrakBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4TkhdBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x5C,
                0x74, 0x6B, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x07,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x5F, (byte) 0x90,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x40, 0x00, 0x00, 0x00,
                0x07, (byte) 0x80, 0x00, 0x00,
                0x04, 0x38, 0x00, 0x00,
        };
        Mp4TkhdBox box = new Mp4TkhdBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4MdiaBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x01, (byte) 0x83,
                0x6D, 0x64, 0x69, 0x61,

                0x00, 0x00, 0x00, 0x20, 0x6D, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
                0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x5F, (byte) 0x90, 0x00, 0x01, 0x5F, (byte) 0x90, 0x55, (byte) 0xC4, 0x00, 0x00,

                0x00, 0x00, 0x00, 0x2D, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x76, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x56, 0x69, 0x64, 0x65, 0x6F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00,

                0x00, 0x00, 0x01, 0x2E, 0x6D, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x14, 0x76, 0x6D, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
                0x64, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x1C, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x75, 0x72, 0x6C, 0x20, 0x00, 0x00, 0x00, 0x01,

                0x00, 0x00, 0x00, (byte) 0xEE, 0x73, 0x74, 0x62, 0x6C, 0x00, 0x00, 0x00, (byte) 0xA2, 0x73, 0x74, (byte) 0x73, 0x64,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, (byte) 0x92, 0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, 0x6C, 0x70, 0x72, 0x6F, 0x2E, 0x72, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11, 0x00, 0x00, 0x00, 0x28, 0x61, 0x76, 0x63, 0x43, 0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04, 0x68, (byte) 0xEE, 0x3C, (byte) 0xB0, 0x00, 0x00, 0x00, 0x14, 0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80, 0x00, 0x2D, (byte) 0xC6, (byte) 0xC0, 0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x14, 0x73, 0x74, 0x73, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x63, 0x6F, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4MdiaBox box = new Mp4MdiaBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4MdhdBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x20,
                0x6D, 0x64, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x02,
                0x00, 0x00, 0x00, 0x03,
                0x00, 0x01, 0x5F, (byte) 0x90,
                0x00, 0x01, 0x5F, (byte) 0x90,
                0x55, (byte) 0xC4, 0x00, 0x00,
        };
        Mp4MdhdBox box = new Mp4MdhdBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4HdlrBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x2D,
                0x68, 0x64, 0x6C, 0x72,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x76, 0x69, 0x64, 0x65,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x56, 0x69, 0x64, 0x65,
                0x6F, 0x48, 0x61, 0x6E,
                0x64, 0x6C, 0x65, 0x72,
                0x00,
        };
        Mp4HdlrBox box = new Mp4HdlrBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4MinfBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x01, 0x2E,
                0x6D, 0x69, 0x6E, 0x66,

                0x00, 0x00, 0x00, 0x14,
                0x76, 0x6D, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,

                0x00, 0x00, 0x00, 0x24,
                0x64, 0x69, 0x6E, 0x66,
                0x00, 0x00, 0x00, 0x1C,
                0x64, 0x72, 0x65, 0x66,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x0C,
                0x75, 0x72, 0x6C, 0x20,
                0x00, 0x00, 0x00, 0x01,

                0x00, 0x00, 0x00, (byte) 0xEE,
                0x73, 0x74, 0x62, 0x6C,
                0x00, 0x00, 0x00, (byte) 0xA2,
                0x73, 0x74, (byte) 0x73, 0x64,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, (byte) 0x92,
                0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, //binelpro.ru
                0x6C, 0x70, 0x72, 0x6F,
                0x2E, 0x72, 0x75, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11,
                0x00, 0x00, 0x00, 0x28,
                0x61, 0x76, 0x63, 0x43,
                0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04,
                0x68, (byte) 0xEE, 0x3C, (byte) 0xB0,
                0x00, 0x00, 0x00, 0x14,
                0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x74, 0x73,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x73, 0x63,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x14,
                0x73, 0x74, 0x73, 0x7A,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x63, 0x6F,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4MinfBox box = new Mp4MinfBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4VmhdBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x14,
                0x76, 0x6D, 0x68, 0x64,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4VmhdBox box = new Mp4VmhdBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4DinfBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x24,
                0x64, 0x69, 0x6E, 0x66,

                0x00, 0x00, 0x00, 0x1C,
                0x64, 0x72, 0x65, 0x66,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x0C,
                0x75, 0x72, 0x6C, 0x20,
                0x00, 0x00, 0x00, 0x01,
        };
        Mp4DinfBox box = new Mp4DinfBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4DrefBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x1C,
                0x64, 0x72, 0x65, 0x66,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x0C,
                0x75, 0x72, 0x6C, 0x20,
                0x00, 0x00, 0x00, 0x01,
        };
        Mp4DrefBox box = new Mp4DrefBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4StblBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, (byte) 0xEE,
                0x73, 0x74, 0x62, 0x6C,

                0x00, 0x00, 0x00, (byte) 0xA2,
                0x73, 0x74, (byte) 0x73, 0x64,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, (byte) 0x92,
                0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, //binelpro.ru
                0x6C, 0x70, 0x72, 0x6F,
                0x2E, 0x72, 0x75, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11,
                0x00, 0x00, 0x00, 0x28,
                0x61, 0x76, 0x63, 0x43,
                0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04,
                0x68, (byte) 0xEE, 0x3C, (byte) 0xB0,
                0x00, 0x00, 0x00, 0x14,
                0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,

                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x74, 0x73,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,

                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x73, 0x63,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,

                0x00, 0x00, 0x00, 0x14,
                0x73, 0x74, 0x73, 0x7A,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,

                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x63, 0x6F,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4StblBox box = new Mp4StblBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4StsdBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, (byte) 0xA2,
                0x73, 0x74, (byte) 0x73, 0x64,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,

                0x00, 0x00, 0x00, (byte) 0x92,
                0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, //binelpro.ru
                0x6C, 0x70, 0x72, 0x6F,
                0x2E, 0x72, 0x75, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11,

                0x00, 0x00, 0x00, 0x28,
                0x61, 0x76, 0x63, 0x43,
                0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04,
                0x68, (byte) 0xEE, 0x3C, (byte) 0xB0,

                0x00, 0x00, 0x00, 0x14,
                0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
        };
        Mp4StsdBox box = new Mp4StsdBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4Avc1Box() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, (byte) 0x92,
                0x61, 0x76, 0x63, 0x31,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x07, (byte) 0x80, 0x04, 0x38,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x48, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x12,
                0x62, 0x69, 0x6E, 0x65, //binelpro.ru
                0x6C, 0x70, 0x72, 0x6F,
                0x2E, 0x72, 0x75, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, // compressorname
                0x00, 0x18, 0x11, 0x11,

                0x00, 0x00, 0x00, 0x28,
                0x61, 0x76, 0x63, 0x43,
                0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04,
                0x68, (byte) 0xEE, 0x3C, (byte) 0xB0,

                0x00, 0x00, 0x00, 0x14,
                0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
        };
        Mp4Avc1Box box = new Mp4Avc1Box(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4AvcCBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x28,
                0x61, 0x76, 0x63, 0x43,
                0x01, 0x64, 0x00, 0x2A,
                (byte) 0xFF, (byte) 0xE1, 0x00, 0x11,
                0x67, 0x64, 0x00, 0x2A, (byte) 0xAC, 0x2B, 0x50, 0x3C, 0x01, 0x13, (byte) 0xF2, (byte) 0xCD, (byte) 0xC0, 0x40, 0x40, 0x40, (byte) 0x80,
                0x01, 0x00, 0x04,
                0x68, (byte) 0xEE, 0x3C, (byte) 0xB0,
        };
        Mp4AvcCBox box = new Mp4AvcCBox(this.trackInfo);
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4BtrtBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x14,
                0x62, 0x74, 0x72, 0x74,
                0x00, 0x1C, (byte) 0x9C, (byte) 0x80,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
                0x00, 0x2D, (byte) 0xC6, (byte) 0xC0,
        };
        Mp4BtrtBox box = new Mp4BtrtBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4SttsBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x74, 0x73,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4SttsBox box = new Mp4SttsBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4StscBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x73, 0x63,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4StscBox box = new Mp4StscBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4StszBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x14,
                0x73, 0x74, 0x73, 0x7A,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4StszBox box = new Mp4StszBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4StcoBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x10,
                0x73, 0x74, 0x63, 0x6F,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
        };
        Mp4StcoBox box = new Mp4StcoBox();
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4MvexBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x28,
                0x6D, 0x76, 0x65, 0x78,

                0x00, 0x00, 0x00, 0x20,
                0x74, 0x72, 0x65, 0x78,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x01,
        };
        Mp4MvexBox box = new Mp4MvexBox(Collections.singletonList(this.trackInfo));
        assertArrayEquals(expect, box.toByteArray());
    }

    @Test
    public void mp4TrexBox() {
        byte[] expect = new byte[]{
                0x00, 0x00, 0x00, 0x20,
                0x74, 0x72, 0x65, 0x78,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x01,
        };
        Mp4TrexBox box = new Mp4TrexBox(1);
        assertArrayEquals(expect, box.toByteArray());
    }
}